package com.smasher.bluetooth.connect;

import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresPermission;

import java.util.Arrays;
import java.util.UUID;

public class ConnectBle extends BaseConnect implements Handler.Callback {


    private UUID targetUuid = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");

    private UUID read = UUID.fromString("0000fff1-0000-1000-8000-00805f9b34fb");

    private UUID write = UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb");


    /**
     * 主服务 UUID，承载多个特征值
     */
    private static final UUID SERVICE_UUID = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");

    /**
     * 模组发给 APP 的通知通道
     */
    private static final UUID NOTIFY_UUID = UUID.fromString("0000fff1-0000-1000-8000-00805f9b34fb");

    /**
     * APP 发送指令给模组
     */
    private static final UUID WRITE_UUID = UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb");

    /**
     * 出厂配置参数，如序列号等
     */
    private static final UUID FACP_UUID = UUID.fromString("0000fff3-0000-1000-8000-00805f9b34fb");

    /**
     * 包含设备信息（制造商、型号等）
     */
    private static final UUID GATT_DEVICE_INFO_UUID = UUID.fromString("0000180a-0000-1000-8000-00805f9b34fb");

    /**
     * GAP 服务，用于蓝牙连接相关
     */
    private static final UUID GAP_SERVICE_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb");

    /**
     * 控制特征值是否开启通知
     * CCCD Descriptor
     */
    private static final UUID CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");


    public static final String TAG = "BleConnect";

    private BluetoothGatt bluetoothGatt;

    public ConnectBle(Context context) {
        super(context);
    }


    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {

        @SuppressLint("MissingPermission")
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            Log.e(TAG, "onConnectionStateChange: " + newState);
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                Log.d(TAG, "已连接至设备");
                gatt.discoverServices();
                if (connectionListener != null) {
                    connectionListener.onConnected(gatt.getDevice());
                }
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.d(TAG, "已断开连接");
                if (connectionListener != null) {
                    connectionListener.onDisconnected(gatt.getDevice());
                }
            } else if (newState == BluetoothProfile.STATE_CONNECTING) {
                Log.d(TAG, "正在连接");
            } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
                Log.d(TAG, "正在断开连接");
            }
        }

        /**
         * GATT 服务列表如下，手机端可以参考使用：
         * Type                                               UUID                           Permissions
         * PRIMARY_SERVICE                       0xFFF0
         * CHARACTERISTIC                         0xFFF1                       WRITE | WRITE_WITHOUT_RESPONSE
         * CHARACTERISTIC                         0xFFF2                       NOTIFY
         * 其中：
         * 0xFFF0   服务号。
         * 0xFFF1   app 发送数据给模组。
         * 0xFFF2   模组发送数据给 app。
         *
         * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
         * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device has been explored
         *     successfully.
         */
        @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            Log.d(TAG, "服务发现完成");
            // 可以开始读写特征值
            Log.i(TAG, "onServicesDiscovered: ");
            for (BluetoothGattService service : gatt.getServices()) {
                Log.e(TAG, "BluetoothGattService uuid: " + service.getUuid() + " service type: " + service.getType());
                UUID serviceUuid = service.getUuid();
                for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
                    Log.e(TAG, "Characteristic uuid: " + characteristic.getUuid());
                    UUID characteristicUuid = characteristic.getUuid();
                    readData(serviceUuid, characteristicUuid, gatt, characteristic);
                }
            }
        }

        @Override
        public void onDescriptorRead(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattDescriptor descriptor, int status, @NonNull byte[] value) {
            super.onDescriptorRead(gatt, descriptor, status, value);
            Log.i(TAG, "onDescriptorRead: ");
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            Log.i(TAG, "onDescriptorWrite: ");
        }

        @Override
        public void onCharacteristicRead(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int status) {
            super.onCharacteristicRead(gatt, characteristic, value, status);
            Log.i(TAG, "==================================================");
            Log.i(TAG, "onCharacteristicRead: " + characteristic.getUuid());
            Log.i(TAG, "onCharacteristicRead: " + Arrays.toString(characteristic.getValue()));
        }

        @Override
        public void onCharacteristicChanged(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) {
            super.onCharacteristicChanged(gatt, characteristic, value);
            Log.i(TAG, "==================================================");
            Log.i(TAG, "onCharacteristicChanged: " + characteristic.getUuid());
            Log.i(TAG, "onCharacteristicChanged: " + Arrays.toString(characteristic.getValue()));
            onDataReceived(value);
        }

        @Override
        public void onServiceChanged(@NonNull BluetoothGatt gatt) {
            super.onServiceChanged(gatt);
            Log.i(TAG, "onServiceChanged: ");
        }
    };


    @Override
    @RequiresPermission(allOf = {Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN})
    public void connectDevice(Context context, BluetoothDevice device) {
        super.connectDevice(context, device);
        Log.i(TAG, "connectBleDevice: " + device);
        String address = device.getAddress();
        Log.i(TAG, "BleDeviceAddress: " + address);
        if (device.getBondState() == BluetoothDevice.BOND_NONE) {
            Log.i(TAG, "设备未配对，准备配对");
            pairedDevice(device);
        } else if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
            Log.i(TAG, "设备已配对，直接连接");
            bluetoothGatt = device.connectGatt(context, false, gattCallback);
        }
    }

    @Override
    @RequiresPermission(allOf = {Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN})
    public void connectDeviceImmediately(Context context, BluetoothDevice device) {
        super.connectDeviceImmediately(context, device);
        Log.i(TAG, "设备已配对，直接连接");
        bluetoothGatt = device.connectGatt(context, false, gattCallback);
    }


    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
    public void disconnect() {
        if (bluetoothGatt != null) {
            bluetoothGatt.disconnect();
            bluetoothGatt.close();
            bluetoothGatt = null;
        }
    }


    @Override
    public boolean handleMessage(@NonNull Message msg) {
        return super.handleMessage(msg);
    }

    /**
     * GATT 服务列表如下，手机端可以参考使用：
     * BLE 模式
     * Service UUID FFF0
     * Write UUID FFF2
     * Read UUID FFF1
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
    private void readData(UUID serviceUuid, UUID characteristicUuid, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        if (serviceUuid.equals(targetUuid)) {
            if (characteristicUuid.equals(read)) {
                Log.i(TAG, "readCharacteristic: " + characteristic.getUuid());

                enableNotification(gatt, characteristic);

                if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) != 0) {
                    boolean readResult = gatt.readCharacteristic(characteristic);
                    Log.i(TAG, "read result: " + readResult);
                }

            } else {
                Log.i(TAG, "characteristicUuid target=: " + read);
                Log.i(TAG, "characteristicUuid check =:" + characteristicUuid);
            }
        } else {
            Log.i(TAG, "serviceUuid 不符合 " + serviceUuid);
        }
    }

    private void onDataReceived(byte[] data) {
        // 解析并处理接收到的数据
        Log.i(TAG, "解析数据长度：" + data.length);
        // 示例：转为字符串
        String receivedStr = new String(data);
        Log.i(TAG, "收到内容: " + receivedStr);
    }


    @SuppressLint("MissingPermission")
    private void enableNotification(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        if (characteristic == null) return;

        // 开启通知
        boolean success = gatt.setCharacteristicNotification(characteristic, true);
        if (!success) {
            Log.e(TAG, "设置通知失败");
            return;
        }
        int properties = characteristic.getProperties();
        Log.i(TAG, "properties: " + properties);
        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);

        if (descriptor == null) {
            Log.e(TAG, "找不到描述符");
            return;
        }

        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        gatt.writeDescriptor(descriptor);
    }

}
